package dao

import (
	"common/biz"
	"common/logs"
	"common/utils"
	"context"
	"core/models/db"
	"core/models/entity"
	"core/repo"
	"crypto/md5"
	"encoding/hex"
	"framework/msError"
	"sync"
)

type AccountDao struct {
	repo *repo.Manager
}

func (d *AccountDao) SaveAccount(ctx context.Context, ac *entity.Account) error {
	table := d.repo.Mongo.Db.Collection("account")
	_, err := table.InsertOne(ctx, ac)
	if err != nil {
		return err
	}
	return nil
}

func (d *AccountDao) SaveUser(ctx context.Context, ac *db.User, password string, count int64) (*db.User, *msError.Error) {
	user := new(db.User)
	user.Username = ac.Username
	user.Password = password
	var err error
	if count < 2 {
		if err = user.PwdCheck(ac.Password); err != nil {
			return nil, biz.AccountOrPasswordError
		}
	}
	if err = user.SaveToken(); err != nil {
		return nil, biz.SqlError
	}
	if err = d.repo.DB.Client.WithContext(ctx).Model(user).Where("username=?", user.Username).Update("token", user.Token).Error; err != nil {
		return nil, biz.SqlError
	}
	return user, nil
}
func (d *AccountDao) AddUser(ctx context.Context, ac *db.User) (*db.User, *msError.Error) {
	user := new(db.User)
	user.Username = ac.Username
	//user.InviteCode = utils.MathInviteCode(8)
	var inviteCode int64
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		for {
			var count int64
			inviteCode = utils.Random(100000, 999999)
			d.repo.DB.Client.WithContext(ctx).Model(user).Where("invite_code=?", inviteCode).Count(&count)
			if count > 0 {
				continue
			}
			wg.Done()
			break
		}
	}()
	wg.Wait()
	user.InviteCode = inviteCode
	if err := user.PwdCheck(ac.Password); err != nil {
		return nil, biz.AccountOrPasswordError
	}
	if ac.InviteCode != 0 {
		user.GetPid(d.repo.DB.Client, ac.InviteCode)
	}
	if err := user.SaveToken(); err != nil {
		logs.Error("用户%v 生成token失败 err=%v", user, err)
		return nil, biz.SqlError
	}
	if err := d.repo.DB.Client.WithContext(ctx).Model(user).Create(&user).Error; err != nil {
		logs.Error("用户%v 注册失败 err=%v", user, err)
		return nil, biz.SqlError
	}
	return user, nil
}

func (d *AccountDao) UserExists(ctx context.Context, account string) *db.User {
	user := new(db.User)
	d.repo.DB.Client.WithContext(ctx).Model(user).Where("username=?", account).First(&user)
	return user
}

func (d *AccountDao) ForgetPassword(ctx context.Context, uid uint, password string) *msError.Error {
	pwdByte := []byte(password)
	md5New := md5.New()
	md5New.Write(pwdByte)
	// hex转字符串
	md5String := hex.EncodeToString(md5New.Sum(nil))
	user := new(db.User)
	if err := d.repo.DB.Client.WithContext(ctx).Model(user).Where("id=?", uid).Update("password", md5String).Error; err != nil {
		logs.Error("用户%d 修改密码失败 err=%v", uid, err)
		return biz.SqlError
	}
	return nil
}

func NewAccountDao(m *repo.Manager) *AccountDao {
	return &AccountDao{
		repo: m,
	}
}
